﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Estimate.Common.Entity;
using System.Text.RegularExpressions;
using Estimate.Common.DBFieldTypes;

namespace Estimate.Common.Estimate
{
    /// <summary>
    /// 根据预报的结果，获得预报的误差方向
    /// </summary>
    public class WaterForecasteDeviation
    {
        private Dictionary<string, AffiliationEntity> affiliations;



        /// <summary>
        /// 预报正确的站
        /// </summary>
        private List<AffiliationEntity> _correctAffiliations;

        /// <summary>
        /// 空报站
        /// </summary>
        private List<AffiliationEntity> _emptyAffiliations;

        /// <summary>
        /// 空报站
        /// </summary>
        private List<AffiliationEntity> _lackAffiliations;

        /// <summary>
        /// ND站
        /// </summary>
        private List<AffiliationEntity> _NDAffiliations;

        

        public WaterForecasteDeviation(AffiliationEntity[] entities)
        {
            affiliations = new Dictionary<string, AffiliationEntity>();
            foreach (AffiliationEntity entity in entities)
            {
                affiliations.Add(entity.code, entity);
            }
            _correctAffiliations = new List<AffiliationEntity>();
            _emptyAffiliations = new List<AffiliationEntity>();
            _lackAffiliations = new List<AffiliationEntity>();
            _NDAffiliations = new List<AffiliationEntity>();
        }

        public void Clear()
        {
            ClearDeviationAffiliations();
        }

        public void ClearDeviationAffiliations()
        {
            _lackAffiliations.Clear();
            _emptyAffiliations.Clear();
            _correctAffiliations.Clear();
            _NDAffiliations.Clear();
        }

        /// <summary>
        /// 使用算好了的semi字符串添加Forecast类
        /// </summary>
        /// <param name="semi">计算好的semi结果</param>
        public void AddForecastBySemiString(string semi, ForeSemiType semitype )
        {
            foreach (string s in Regex.Split(semi, @"\|", RegexOptions.IgnoreCase))
            {
                if (s.Trim().Length < 5)
                    continue;
                WaterForecast forecast = new WaterForecast();
                string[] oserial = Regex.Split(s, @"\;", RegexOptions.IgnoreCase);

                if (oserial[0] == "58265" || oserial[0] == "58358")
                    continue;
                string station = "";
                if (oserial[0] == "58248")
                    station = "58252";
                else if (oserial[0] == "58154")
                    station = "58151";
                else
                    station = oserial[0];

                forecast.SetSemiResult(s,semitype);
                forecast.FStNum = station;
                AffiliationEntity entity = affiliations[ forecast.FStNum];

                if( forecast.WaterfallLevelInspection == EstimateValue.WaterfallLevelInspectionResult.NA11 ||
                    forecast.WaterfallLevelInspection == EstimateValue.WaterfallLevelInspectionResult.NA12)
                    _correctAffiliations.Add(entity);
                else if(  forecast.WaterfallLevelInspection == EstimateValue.WaterfallLevelInspectionResult.NB11 ||
                    forecast.WaterfallLevelInspection == EstimateValue.WaterfallLevelInspectionResult.NB12)
                    _emptyAffiliations.Add(entity);
                else if(  forecast.WaterfallLevelInspection == EstimateValue.WaterfallLevelInspectionResult.NC11 ||
                    forecast.WaterfallLevelInspection == EstimateValue.WaterfallLevelInspectionResult.NC12)
                    _lackAffiliations.Add(entity);
                else
                    _NDAffiliations.Add(entity);
            }

        }

        /// <summary>
        /// 计算一组站点的平均位置 
        /// </summary>
        /// <param name="affiliations"></param>
        /// <returns></returns>
        private AffiliationEntity calculateAveragePosition(List<AffiliationEntity> affiliations)
        {
            AffiliationEntity result = new AffiliationEntity();
            result.lontitude = 0f;
            result.latitude = 0f;
            int count = 0;
            foreach (AffiliationEntity entity in affiliations)
            {
                count++;
                result.lontitude += entity.lontitude;
                result.latitude += entity.latitude;
            }
            result.lontitude /= count;
            result.latitude /= count;
            return result;
        }

        public WaterForecasteDeviationResult GetResult()
        {
            if (_correctAffiliations.Count > 0 && _emptyAffiliations.Count == 0 && _lackAffiliations.Count == 0)
            {//落区无偏差
                return new WaterForecasteDeviationResult(DeviationKind.NoDeviation);
            }
            else if (_correctAffiliations.Count > 0 && _emptyAffiliations.Count > 0 && _lackAffiliations.Count == 0)
            {//则落区向从正确预报站点的平均经纬度指向空报预报站点的平均经纬度的矢量方向偏差
                AffiliationEntity correct = calculateAveragePosition(this._correctAffiliations);
                AffiliationEntity empty = calculateAveragePosition(this._emptyAffiliations);
                return new WaterForecasteDeviationResult(empty.lontitude - correct.lontitude, empty.latitude - correct.latitude, _lackAffiliations.Count, _emptyAffiliations.Count);
            }
            else if (_correctAffiliations.Count > 0 && _emptyAffiliations.Count == 0 && _lackAffiliations.Count > 0)
            {//落区向从漏报预报站点的平均经纬度指向正确预报站点的平均经纬度的矢量方向偏差
                AffiliationEntity correct = calculateAveragePosition(this._correctAffiliations);
                AffiliationEntity lack = calculateAveragePosition(this._lackAffiliations);
                return new WaterForecasteDeviationResult(correct.lontitude - lack.lontitude, correct.latitude - lack.latitude, _lackAffiliations.Count, _emptyAffiliations.Count);
            }
            else if (_correctAffiliations.Count > 0 && _emptyAffiliations.Count > 0 && _lackAffiliations.Count > 0)
            {//以上两个矢量和方向偏差
                AffiliationEntity empty = calculateAveragePosition(this._emptyAffiliations);
                AffiliationEntity lack = calculateAveragePosition(this._lackAffiliations);
                return new WaterForecasteDeviationResult(empty.lontitude - lack.lontitude, empty.latitude - lack.latitude, _lackAffiliations.Count, _emptyAffiliations.Count);
            }
            else if (_correctAffiliations.Count == 0 && _emptyAffiliations.Count > 0 && _lackAffiliations.Count > 0)
            {//从漏报预报站点的平均经纬度指向空报站点的平均经纬度的矢量预报反向。
                AffiliationEntity empty = calculateAveragePosition(this._emptyAffiliations);
                AffiliationEntity lack = calculateAveragePosition(this._lackAffiliations);
                return new WaterForecasteDeviationResult(lack.lontitude - empty.lontitude, lack.latitude - empty.latitude, _lackAffiliations.Count, _emptyAffiliations.Count);
            }
            else if (_correctAffiliations.Count == 0 && _emptyAffiliations.Count > 0 && _lackAffiliations.Count == 0)
            {//仅记为空报或漏报。 
                return new WaterForecasteDeviationResult(DeviationKind.AllEmpty);
            }
            else if (_correctAffiliations.Count == 0 && _emptyAffiliations.Count == 0 && _lackAffiliations.Count > 0)
            {
                return new WaterForecasteDeviationResult(DeviationKind.AllLack);
            }
            else
                return new WaterForecasteDeviationResult();
            
        }


    }
}
